<template>
  <el-dialog :visible.sync="dialogVisible" width="80%" @closed="dialogClosed">
    <el-form ref="searchForm" :inline="true" :model="search" :rules="rules">
      <el-form-item label="项目名称" prop="sysCode">
        <el-select v-model="search.sysCode" @change="getGroupList">
          <el-option v-for="item in sysList" :key="item.code" :label="item.name" :value="item.code"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="服务名称" prop="groupCode">
        <el-select v-model="search.groupCode"><el-option v-for="item in groupList" :key="item.code" :label="item.name" :value="item.code"></el-option></el-select>
      </el-form-item>
      <el-form-item><el-button type="primary" icon="el-icon-search" @click="searchTree">查询</el-button></el-form-item>
    </el-form>

    <el-row type="flex" justify="space-between">
      <el-col :span="10">
        <el-card shadow="hover" class="slot-header">
          <div slot="header">
            <i class="el-icon-setting"></i>
            报文头配置
          </div>
          <template v-if="data && data.length">
            <div class="card-content">
              <menu-tree :data="data" ref="treemenu" :optionTree="optionTree" :onlyChild="true" :expandClick="false" :getAddList="getAddList" :allowDrag="allowDrag" :allowDrop="allowDrop" @handlerClick="handlerClick"/>
            </div>
            <el-button type="primary" icon="el-icon-document-checked" class="save-btn" @click="saveFlow">保存报文头配置</el-button>
          </template>
        </el-card>
      </el-col>

      <el-col :span="13">
        <el-card shadow="hover" class="slot-header">
          <div slot="header">
            <i class="el-icon-box"></i>
            报文头节点信息
          </div>
          <template v-if="formList && formList.length">
            <div class="card-content">
              <el-form ref="dataForm" label-width="100px" :model="formData">
                <el-form-item v-for="(item, index) in formList" :key="item.key" :label="item.label" :rules="item.rules" :prop="item.key">
                  <el-select v-if="item.type === 'select'" v-model="formData[item.key]" :placeholder="`请选择${item.label}`" @change="changeType">
                    <el-option v-for="option in getDicData(item.dicDataKey)" :key="option.value" :value="option.value" :label="option.label"></el-option>
                  </el-select>
                  <el-input v-else v-model="formData[item.key]" :placeholder="`请输入${item.label}`" :maxlength="item.maxlength" :show-word-limit="item.showWordLimit"></el-input>
                </el-form-item>

                <el-form-item v-for="(item, index) in formTypeList" :key="item.key" :label="item.label" :rules="item.rules" :prop="item.key">
                  <el-select v-if="item.type === 'select'" v-model="formData[item.key]" :placeholder="`请选择${item.label}` "@change="$forceUpdate()">
                    <el-option v-for="option in getDicData(item.dicDataKey)" :key="option.value" :value="option.value" :label="option.label"></el-option>
                  </el-select>
                  <el-input v-else v-model="formData[item.key]" :placeholder="`请输入${item.label}`" :maxlength="item.maxlength" :show-word-limit="item.showWordLimit"></el-input>
                </el-form-item>
              </el-form>
            </div>
            <el-button type="primary" icon="el-icon-circle-check" class="save-btn" @click="saveInfo">保存节点信息</el-button>
          </template>
        </el-card>
      </el-col>
    </el-row>
  </el-dialog>
</template>

<script>
import { createTree,addObj,putObj } from '@/api/pre/code'
import { remote } from '@/api/admin/dict'
import MenuTree from '@/components/menu-tree/main'

import { getSysList } from '@/api/pre/insystem'
import { getGroupList ,getGroupListBySysCode} from '@/api/pre/group'
import { addList, dictType, formMap, changeForm } from './config'
import _cloneDeep from 'lodash/cloneDeep'
import _isEmpty from 'lodash/isEmpty'
import { dictText } from '@/filters'

export default {
  name: 'codeDetail',
  components: {
    MenuTree
  },
  props: {
    visible: {
      type: Boolean,
      default() {
        return false
      }
    },
    searchData: {
      type: Object,
      default() {
        return {}
      }
    }
  },
  data() {
    return {
      dialogVisible: this.visible,
      search: {
        sysId: '',
        sysCode: '',
        groupCode: ''
      },
      sysList: [],
      groupList: [],

      rules: {
        sysCode: [{ required: true, message: '项目名称不能为空' }],
        groupCode: [{ required: true, message: '服务名称不能为空' }]
      },
      data: [],
      optionTree: {},
      lastTargetData: null,
      targetData: {},
      targetNode: {},
      formList: [],
      formData: {},
      addList: null,

      formTypeList: [],

      nowTreeId: null, //当前点击的树id

      //报文类型
      reportList: [],
      whetherList: [],
      charsetList: [],
      //填充类型
      fillTypeList: [
        {
          label: '字符',
          value: 'char'
        },
        {
          label: '字节',
          value: 'byte'
        }
      ],
      fillLocationList: [
        {
          label: '左边填充',
          value: 'left'
        },
        {
          label: '右边填充',
          value: 'right'
        }
      ],
      //xml输出格式
      xmlList: [
        {
          label: '根据系统来换行',
          value: ' '
        },
        {
          label: '不换行',
          value: 'no'
        },
        {
          label: '用\\n换行',
          value: 'n'
        },
        {
          label: '用\\r\\n换行',
          value: 'rn'
        }
      ],
      //位图格式
      bitmapList: [
        {
          label: '二进制',
          value: 'bin'
        },
        {
          label: '字符串',
          value: 'hex'
        }
      ]
    }
  },
  watch: {
    visible() {
      this.dialogVisible = this.visible
      if (this.visible && !_isEmpty(this.searchData)) {
        this.search = _cloneDeep(this.searchData)
        this.getGroupList(this.searchData.sysCode,true).then(() => {
          this.searchTree()
        })
      }
    }
  },
  created() {
    this.getSysList()
    this.getDictList('report_type', 'reportList')
    this.getDictList('whether_status', 'whetherList')
    this.getDictList('charset_type', 'charsetList')
  },
  methods: {
    getSysList() {
      getSysList().then(res => {
        this.sysList = res.data.data
      })
    },
    getGroupList(value,flag) {
      return getGroupListBySysCode(value).then(res => {
        this.groupList = res.data.data
        if (this.groupList.length) {
          if (!flag) this.search.groupCode = this.groupList[0].code
        }else{
          this.search.groupCode = ""
        }
      })
    },
    getDictList(type, item) {
      remote(type).then(response => {
        const code = response.data.code
        if (code === 0) {
          this[item] = response.data.data
        }
      })
    },
    // 获取数结构
    searchTree() {
      this.$refs.searchForm.validate(valid => {
        if (!valid) {
          return
        }

        let sysCommPkt = {
          systemCode: this.search.sysCode,
          groupCode: this.search.groupCode,
          transCode: "input"
        };
        createTree(sysCommPkt).then(res => {
          if(res.data.data == null || res.data.data.content == null){
            this.searchData.pktId = null
            this.data = [{
                          "id": 0,
                          "label": this.search.sysCode + "."+this.search.groupCode+".报文头配置",
                          "children": [{
                            "id": 1,
                            "label": "组包",
                            "children": [],
                            "dropInner": true, //新增节点是兄弟节点还是子节点
                            "pktType": "pack",
                            "addType": 'single', //新增的节点有哪些内容
                            "rootType": 'pack', //新增的节点有哪些内容
                            "noDrag": true
                          }, {
                            "id": 2,
                            "label": "解包",
                            "children": [],
                            "dropInner": true,
                            "pktType": "unpack",
                            "addType": 'single',
                            "rootType": 'unpack', //新增的节点有哪些内容
                            "noDrag": true
                          }],
                          "dropInner": true,
                          "root": true,
                          "pktType": null
                        }]
          }else{
            this.data = []
            this.searchData.pktId = res.data.data.pktId
            this.data.push(res.data.data.content)
            // this.initPolicyType(this.data[0])
          }
        })
      })
    },
    // 弹窗关闭时的处理
    dialogClosed() {
      this.$refs.searchForm.resetFields()
      this.$emit('update:visible', false)

      this.search = {}
      this.data = []
      this.formList = []
      this.targetData = {}
    },
    // 获取addList
    getAddList(data, node) {
      if (data.addType && addList[data.addType]) {
        // 对this.addList进行初始化赋值，尤其是dataModel的赋值
        this.addList = addList[data.addType].map(addItem => {
          const dataModel = {
            pktType: addItem.value
          }
          formMap[addItem.value].forEach(item => {
            dataModel[item.key] = ''
          })

          let addData = {
            label: addItem.label,
            pktType: addItem.value,
            value: addItem.value,
            addType: addItem.addType,
            rootType: data.rootType == data.pktType ? data.pktType : data.rootType,
            onlyChild: true,
            dropInner: true,
            dataModel
          }

          //给每个节点存入报文类型字段
          if (data.pktType === 'policy'){
            addData.type = data.dataModel.type ? data.dataModel.type : ''
          }else{
            addData.type = data.type ? data.type : ''
          }
          return addData
        })
      }

      // 若addList已赋值，则直接返回
      return this.addList
    },
    //允许放置
    allowDrop(draggingNode, dropNode, type) {
      //交易码配置每个节点只能有一个子节点
      if (dropNode.parent.childNodes && dropNode.parent.childNodes.length >= 1){
        if (dropNode.data.children && dropNode.data.children.length >= 1) {
          return false
        }
        return type === 'inner'
      }
      //不是报文的节点不能拖拽到组包解包下
      // if ((dropNode.data.pktType === 'pack' || dropNode.data.pktType === 'unpack') && draggingNode.data.pktType !== 'policy'){
      //   return false
      // }
      // 根节点，只能放置为子节点
      if (dropNode.data.root) {
        return type === 'inner'
      }
      return true
    },
    //允许拖拽
    allowDrag(node){
      if (node.data.noDrag) {
        return false
      }
      return true
    },
    // 获取字典内容
    getDicData(key) {
      return this[key]
    },
    checkWarning() {
      if (!this.targetData.dataModel) {
        return false
      }

      const value = this.targetData.value
      if (value && value !== 'save') {
        // 若为后期添加的节点，且未保存过，直接返回warning
        return true
      }

      // 初始化就存在的节点，或者是保存过的节点，则直接判断前后的数据是否一致
      const diff = JSON.stringify(this.targetData.dataModel) !== JSON.stringify(this.formData)
      this.targetData.formData = this.formData
      // 若不一致，直接warning。若一致，后期添加的节点返回success，初始化存在的节点返回null
      this.$set(this.targetData, 'status', diff ? 'warning' : value ? 'success' : null)
      return diff
    },
    // 点击树结构节点时的处理
    handlerClick(data, node) {
      this.checkWarning()
      if (data.root || !data.dataModel) {
        this.formList = []
        return
      }

      if (this.nowTreeId != data.id) {
        this.formTypeList = []
        this.nowTreeId = data.id
      }

      //渲染报文子节点表单的变化
      if (data.pktType === 'policy') {
        this.formTypeList = changeForm[data.rootType][data.pktType][data.dataModel.type]
      } else {
        this.formTypeList = changeForm[data.rootType][data.pktType][data.type]
      }

      // 获取当前节点的dataModel，渲染form
      const dataModel = data.dataModel
      if (this.formTypeList && this.formTypeList.length){
        this.formTypeList.forEach(item => {
          if (item.defaultVal && !dataModel[item.key]) dataModel[item.key] = item.defaultVal
        })
      }
      const list = []
      formMap[data.pktType].forEach(item => {
        const value = data.dataModel[item.key]
        // value为null时，不渲染
        if (value !== null) {
          list.push(item)
        }
      })
      this.targetData = data
      this.targetNode = node
      this.formList = list
      if (!data.formData) {
        data.formData = _cloneDeep(dataModel)
      }

      //当没有保存过节点信息时
      if (data.status !== 'success'){
        this.formData = _cloneDeep(dataModel)
      }else{
        this.formData = data.formData
      }

    },
    changeType(item) {
      this.formTypeList = changeForm[this.targetData.rootType][this.targetData.pktType][item]
      if (this.formTypeList && this.formTypeList.length){
        this.formTypeList.forEach(form => {
          if (form.defaultVal) this.formData[form.key] = form.defaultVal
        })
      }
    },
    saveInfo() {

      if (this.targetData.pktType !== 'policy' &&!this.targetData.type){
        this.$message.error('请先保存报文节点信息')
        return false
      }


      this.$refs.dataForm.validate(valid => {
        if (!valid) {
          return
        }

        let baseModel = formMap[this.targetData.pktType]
        let useModel = this.formTypeList ? [...baseModel,...this.formTypeList] : [...baseModel]
        // TODO 请求接口保存当前节点信息
        this.$set(this.targetData, 'status', 'success') // 成功时为success，失败时为error
        this.targetData.dataModel = {}
        useModel.forEach(item => {
          this.targetData.dataModel[item.key] = this.formData[item.key]
        })
        this.targetData.dataModel.pktType = this.targetData.pktType
        this.formData = {}
        this.formData = this.targetData.dataModel
        // this.targetData.dataModel = this.formData

        if (this.targetData.value) {
          // 若是后期添加的节点，则有value属性，保存后，将value属性的值改为save
          this.targetData.value = 'save'
        }


        if (this.targetData.pktType === 'policy'){
          let label = dictText(this.targetData.dataModel.type, this.reportList)
          this.targetData.label = label + '：' +this.targetData.dataModel.desc
        }else{
          let label = dictText(this.targetData.dataModel.pktType, dictType)
          let name = this.targetData.dataModel.name ? this.targetData.dataModel.name+'-'+this.targetData.dataModel.desc : this.targetData.dataModel.desc
          this.targetData.label = label + '：' + name
        }

        this.$message.success('节点信息保存成功！')


        if (this.targetData.pktType === 'policy') {
          this.setPolicyType(this.targetNode.data)
        }
      })


    },
    //初始化报文节点信息时，给报文子节点添加报文类型字段
    initPolicyType(data){
      if (data.children && data.children.length){
        data.children.forEach(item => {
          if (item.pktType === 'policy'){
            if (item.children && item.children.length){
              item.children.forEach(key => {
                if (key.pktType === 'policy'){
                  this.initPolicyType(item)
                  return false;
                }
                key.type = item.type
              })
            }
          }else{
            this.initPolicyType(item)
          }
        })
      }
    },
    //保存报文节点信息时，给报文子节点添加报文类型字段
    setPolicyType(data){
      if (data.children && data.children.length){
        data.children.forEach(item => {
          //一级报文下面的二级报文的子节点不受一级报文影响
          if (item.pktType === 'policy'){
            return false;
          }
          item.type = this.targetData.dataModel.type
          if (item.children && item.children.length){
            this.setPolicyType(item)
          }
        })
      }
    },
    saveFlow() {
      if (this.checkWarning()) {
        this.$message.error('请先保存节点信息')
        return
      }
      // 递归检查this.data是否有status为warning或者error的状态
      const checkError = arr => {
        return arr.some(item => {
          if (item.status === 'warning' || item.status === 'error') {
            return true
          }
          if (item.children && item.children.length) {
            return checkError(item.children)
          }
        })
      }

      if (checkError(this.data)) {
        this.$message.error('请先保存节点信息')
        return
      }

      // TODO 请求保存交易码接口
      let param = {
            systemCode: this.search.sysCode,
            groupCode: this.search.groupCode,
            transCode: "input",
            data: this.data[0],
            pktId: this.searchData.pktId
          }
      if(param.pktId == null){
        addObj(param).then(response => {
          this.$message.success('交易码配置保存成功！')
          this.$emit('update')
          this.dialogVisible = false
        })
      }else{
        putObj(param).then(response => {
          this.$message.success('交易码配置更新成功！')
          this.$emit('update')
          this.dialogVisible = false
        })
      }
    }
  }
}
</script>

<style></style>
